package mock

import (
	"bytes"
	"gitee.com/bigmouth/quick-mock/src/infrastructure/config"
	"gitee.com/bigmouth/quick-mock/src/infrastructure/log"
	"gitee.com/bigmouth/quick-mock/src/infrastructure/server"
	"github.com/gin-gonic/gin"
	jsoniter "github.com/json-iterator/go"
	"io/ioutil"
	"net/http"
)

/**
* @Author: huangyi
* @Date: 2022/7/7 00:36
 */

var traceIdKeys = []string{
	"trace_id", "trace-id", "Trace-Id", "Trace_Id", "TraceId", "Trace-ID", "Trace_ID",
}

func loadExtTraceIdKeys() {
	extTraceIds := config.GetConfig().Mock.GetExtTraceIds()
	if len(extTraceIds) == 0 {
		log.Info("not ext traceIds, all traceIdKeys=%v", traceIdKeys)
		return
	}
	allTraceIdKeys := append([]string{}, extTraceIds...)
	allTraceIdKeys = append(allTraceIdKeys, traceIdKeys...)
	traceIdKeys = allTraceIdKeys
	log.Info("load ext traceIds, all traceIdKeys=%v", allTraceIdKeys)
}

func MockByTraceId(c *gin.Context) {
	// namespace
	for _, traceIdKey := range traceIdKeys {
		namespace := c.GetHeader(traceIdKey)
		if namespace != "" {
			mockByNamespace(c, namespace)
			return
		}
	}
	// 补充从body查找trace_id
	if c.Request.Method != http.MethodGet {
		bodyData, err := c.GetRawData()
		if err != nil {
			c.AbortWithStatusJSON(http.StatusInternalServerError, server.Fail("获取body json异常:%s", err.Error()))
			return
		}
		newBodyData := make([]byte, len(bodyData))
		copy(newBodyData, bodyData)
		c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(newBodyData))
		bodyMap := make(map[string]interface{})
		if err := jsoniter.Unmarshal(bodyData, &bodyMap); err != nil {
			c.AbortWithStatusJSON(http.StatusInternalServerError, server.Fail("反序列化body json异常:%s", err.Error()))
			return
		}
		for _, traceIdKey := range traceIdKeys {
			if namespaceObj, ok := bodyMap[traceIdKey]; ok {
				namespace := namespaceObj.(string)
				if namespace != "" {
					mockByNamespace(c, namespace)

					return
				}
			}

		}
	}

	c.AbortWithStatusJSON(http.StatusNotFound, server.Fail("无法找到traceId"))

}
